package com.netty.reactot.reactorthread;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 单线程，负责监听和分发
 */
public class MultReactor implements Runnable {

    Selector selector;
    public MultReactor(int port) throws IOException {
        //打开多路复用器
        selector = selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(port));
        //设置非阻塞
        serverSocketChannel.configureBlocking(false);
        //进行注册监听事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT,new MultAcceptor(this.selector,serverSocketChannel));

    }

    public void run() {
        //分发任务
        try {
            selector.select();//阻塞
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()){
                //对事件进行分发
                dispatch(iterator.next());
                //分发完成后，删除key，防止重复key
                iterator.remove();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void dispatch(SelectionKey key) {
        // 如果是accept，这里的runnable就是Acceptor
        // 如果是read事件，这里的runnable就是handler
        // 然后在这里通过key获取这个attachment,执行他的run方法，记住，这里并没有开启线程，所以叫做单Reactor单线程模型
        Runnable runnable=(Runnable)key.attachment();
        if(runnable!=null){
            runnable.run();
        }
    }
}
